package org.teremail.delivery;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.teremail.common.Log;
import org.teremail.mailbox.MailboxService;
import org.teremail.mailbox.MessageDAO;
import org.teremail.message.Message;
import org.teremail.store.Store;

import com.google.common.collect.Lists;
import com.google.inject.Inject;

public class ExchangeImpl implements Exchange {

    private final static Log log = Log.getLog(ExchangeImpl.class);
    private final MailboxService mailboxService;
    private final ExecutorService pool;
    private final Store store;
    private final MessageDAO messageDAO;
    private MessageHandler messageHandler;

    @Inject
    public ExchangeImpl(MailboxService ms, MessageDAO messageDAO, Store store, 
            MessageHandler h) {
        this.mailboxService = ms;
        this.messageDAO = messageDAO;
        this.store = store;
        this.messageHandler = h;
        pool = Executors.newFixedThreadPool(1);
    }

    public Collection<Future<?>> deliver(final Envelope envelope) {
        
        final Message message = envelope.getMessage();
        final Envelope savedEnvelope;
        if (message.getId() == Message.UNSAVED_ID) {
            Message savedMessage = (Message) messageDAO.save(message);
            savedEnvelope = new Envelope(envelope.getSender(), 
                    envelope.getRecipients(), savedMessage);
        } else {
            savedEnvelope = envelope;
        }
        
        log.info("Deliver sender: %s, messageId: %s", 
                envelope.getSender().toString(),
                envelope.getMessage().getId());
        
        List<Future<?>> futures = Lists.newArrayList();
        Future<?> f = pool.submit(new Runnable() {
            public void run() {
                messageHandler.handle(savedEnvelope);
            }
        });
        futures.add(f);
        
        return futures;
    }

    public Store getStore() {
        return store;
    }

    /**
     * @return the mailboxService
     */
    public MailboxService getMailboxService() {
        return mailboxService;
    }
}
